import { css } from '@emotion/css';
import React, { SyntheticEvent } from 'react';

import {
  DataSourcePluginOptionsEditorProps,
  GrafanaTheme2,
  onUpdateDatasourceJsonDataOption,
  onUpdateDatasourceSecureJsonDataOption,
  SelectableValue,
  updateDatasourcePluginJsonDataOption,
  updateDatasourcePluginResetOption,
} from '@grafana/data';
import {
  Alert,
  FieldSet,
  InlineField,
  InlineFieldRow,
  InlineSwitch,
  Input,
  Link,
  SecretInput,
  Select,
  useStyles2,
  SecureSocksProxySettings,
} from '@grafana/ui';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { config } from 'app/core/config';
import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits';
import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseFields';

import { MSSQLAuthenticationType, MSSQLEncryptOptions, MssqlOptions } from '../types';

export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<MssqlOptions>) => {
  const { options, onOptionsChange } = props;
  const styles = useStyles2(getStyles);
  const jsonData = options.jsonData;

  useMigrateDatabaseFields(props);

  const onResetPassword = () => {
    updateDatasourcePluginResetOption(props, 'password');
  };

  const onDSOptionChanged = (property: keyof MssqlOptions) => {
    return (event: SyntheticEvent<HTMLInputElement>) => {
      onOptionsChange({ ...options, ...{ [property]: event.currentTarget.value } });
    };
  };

  const onSkipTLSVerifyChanged = (event: SyntheticEvent<HTMLInputElement>) => {
    updateDatasourcePluginJsonDataOption(props, 'tlsSkipVerify', event.currentTarget.checked);
  };

  const onEncryptChanged = (value: SelectableValue) => {
    updateDatasourcePluginJsonDataOption(props, 'encrypt', value.value);
  };

  const onAuthenticationMethodChanged = (value: SelectableValue) => {
    onOptionsChange({
      ...options,
      ...{
        jsonData: { ...jsonData, ...{ authenticationType: value.value } },
        secureJsonData: { ...options.secureJsonData, ...{ password: '' } },
        secureJsonFields: { ...options.secureJsonFields, ...{ password: false } },
        user: '',
      },
    });
  };

  const onConnectionTimeoutChanged = (connectionTimeout?: number) => {
    updateDatasourcePluginJsonDataOption(props, 'connectionTimeout', connectionTimeout ?? 0);
  };

  const authenticationOptions: Array<SelectableValue<MSSQLAuthenticationType>> = [
    { value: MSSQLAuthenticationType.sqlAuth, label: 'SQL Server Authentication' },
    { value: MSSQLAuthenticationType.windowsAuth, label: 'Windows Authentication' },
  ];

  const encryptOptions: Array<SelectableValue<string>> = [
    { value: MSSQLEncryptOptions.disable, label: 'disable' },
    { value: MSSQLEncryptOptions.false, label: 'false' },
    { value: MSSQLEncryptOptions.true, label: 'true' },
  ];

  const shortWidth = 15;
  const longWidth = 46;
  const labelWidthSSL = 25;
  const labelWidthDetails = 20;

  return (
    <>
      <FieldSet label="MS SQL Connection" width={400}>
        <InlineField labelWidth={shortWidth} label="Host">
          <Input
            width={longWidth}
            name="host"
            type="text"
            value={options.url || ''}
            placeholder="localhost:1433"
            onChange={onDSOptionChanged('url')}
          ></Input>
        </InlineField>
        <InlineField labelWidth={shortWidth} label="Database">
          <Input
            width={longWidth}
            name="database"
            value={jsonData.database || ''}
            placeholder="database name"
            onChange={onUpdateDatasourceJsonDataOption(props, 'database')}
          ></Input>
        </InlineField>
        <InlineField
          label="Authentication"
          labelWidth={shortWidth}
          htmlFor="authenticationType"
          tooltip={
            <ul className={styles.ulPadding}>
              <li>
                <i>使用用户名和密码</i>这是连接到MS SQL Server的默认机制。输入
                SQL Server身份验证登录或域\用户格式的Windows身份验证登录.
              </li>
              <li>
                <i>身份验证</i> Windows集成安全性-已登录的用户单次登录
                已登录到Windows并已为MS SQL Server启用此选项.
              </li>
            </ul>
          }
        >
          <Select
            value={jsonData.authenticationType || MSSQLAuthenticationType.sqlAuth}
            inputId="authenticationType"
            options={authenticationOptions}
            onChange={onAuthenticationMethodChanged}
          ></Select>
        </InlineField>
        {jsonData.authenticationType === MSSQLAuthenticationType.windowsAuth ? null : (
          <InlineFieldRow>
            <InlineField labelWidth={shortWidth} label="User">
              <Input
                width={shortWidth}
                value={options.user || ''}
                placeholder="user"
                onChange={onDSOptionChanged('user')}
              ></Input>
            </InlineField>
            <InlineField label="Password" labelWidth={shortWidth}>
              <SecretInput
                width={shortWidth}
                placeholder="Password"
                isConfigured={options.secureJsonFields && options.secureJsonFields.password}
                onReset={onResetPassword}
                onBlur={onUpdateDatasourceSecureJsonDataOption(props, 'password')}
              ></SecretInput>
            </InlineField>
          </InlineFieldRow>
        )}
      </FieldSet>

      {config.secureSocksDSProxyEnabled && (
        <SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
      )}

      <FieldSet label="TLS/SSL Auth">
        <InlineField
          labelWidth={labelWidthSSL}
          htmlFor="encrypt"
          tooltip={
            <>
              确定是否或在多大程度上与服务器协商安全SSL TCP/IP连接.
              <ul className={styles.ulPadding}>
                <li>
                  <i>禁用</i> - 客户端和服务器之间发送的数据未加密.
                </li>
                <li>
                  <i>失败</i> - 在客户端和服务器之间发送的数据在登录数据包之外没有加密。（默认）
                </li>
                <li>
                  <i>正确</i> - 客户端和服务器之间发送的数据已加密.
                </li>
              </ul>
              如果你&apos;如果使用旧版本的Microsoft SQL Server（如2008和2008R2），则可能需要禁用加密才能连接.
            </>
          }
          label="Encrypt"
        >
          <Select
            options={encryptOptions}
            value={jsonData.encrypt || MSSQLEncryptOptions.false}
            inputId="encrypt"
            onChange={onEncryptChanged}
          ></Select>
        </InlineField>

        {jsonData.encrypt === MSSQLEncryptOptions.true ? (
          <>
            <InlineField labelWidth={labelWidthSSL} htmlFor="skipTlsVerify" label="Skip TLS Verify">
              <InlineSwitch
                id="skipTlsVerify"
                onChange={onSkipTLSVerifyChanged}
                value={jsonData.tlsSkipVerify || false}
              ></InlineSwitch>
            </InlineField>
            {jsonData.tlsSkipVerify ? null : (
              <>
                <InlineField
                  labelWidth={labelWidthSSL}
                  tooltip={
                    <span>
                      包含对SQL Server进行签名的CA的公钥证书的文件的路径
                        证明书服务器证书自签名时需要.
                    </span>
                  }
                  label="TLS/SSL Root Certificate"
                >
                  <Input
                    value={jsonData.sslRootCertFile || ''}
                    onChange={onUpdateDatasourceJsonDataOption(props, 'sslRootCertFile')}
                    placeholder="TLS/SSL root certificate file path"
                  ></Input>
                </InlineField>
                <InlineField labelWidth={labelWidthSSL} label="Hostname in server certificate">
                  <Input
                    placeholder="Common Name (CN) in server certificate"
                    value={jsonData.serverName || ''}
                    onChange={onUpdateDatasourceJsonDataOption(props, 'serverName')}
                  ></Input>
                </InlineField>
              </>
            )}
          </>
        ) : null}
      </FieldSet>

      <ConnectionLimits labelWidth={shortWidth} options={options} onOptionsChange={onOptionsChange} />

      <FieldSet label="MS SQL details">
        <InlineField
          tooltip={
            <span>
              按时间间隔自动分组的下限。例如，建议设置为写入频率
              <code>1m</code> 如果您的数据是每分钟写入一次.
            </span>
          }
          label="Min time interval"
          labelWidth={labelWidthDetails}
        >
          <Input
            placeholder="1m"
            value={jsonData.timeInterval || ''}
            onChange={onUpdateDatasourceJsonDataOption(props, 'timeInterval')}
          ></Input>
        </InlineField>
        <InlineField
          tooltip={
            <span>
              连接到数据库时，在取消请求之前等待的秒数。默认值为{' '}
              <code>0</code>, 意味着没有超时.
            </span>
          }
          label="Connection timeout"
          labelWidth={labelWidthDetails}
        >
          <NumberInput
            placeholder="60"
            min={0}
            value={jsonData.connectionTimeout}
            onChange={onConnectionTimeoutChanged}
          ></NumberInput>
        </InlineField>
      </FieldSet>

      <Alert title="User Permission" severity="info">
        数据库用户只应被授予对指定的数据库和您想要的表的SELECT权限查询.
        Grafana不会验证查询是否安全，因此查询可以包含任何SQL语句。例如,
        诸如 <code>USE otherdb;</code> 和 <code>DROP TABLE user;</code> 将被执行.
        为了防止这种情况，我们 <em>非常</em> 建议您创建具有受限权限的特定MS SQL用户.
        查看{' '}
        <Link rel="noreferrer" target="_blank" href="http://docs.grafana.org/features/datasources/mssql/">
          Microsoft SQL Server数据源文档
        </Link>{' '}
        更多信息.
      </Alert>
    </>
  );
};

function getStyles(theme: GrafanaTheme2) {
  return {
    ulPadding: css({
      margin: theme.spacing(1, 0),
      paddingLeft: theme.spacing(5),
    }),
  };
}
